﻿using System;
using System.Collections.Generic;
using System.Linq;
using Orchard;
using Orchard.Data;
using Orchard.Localization;
using Orchard.Logging;
using Whatsnexx.Models;
using Whatsnexx.TicketBus.TicketBusClient;
using Whatsnexx.TicketBus.TicketBusClient.DataModel;
using Attribute = Whatsnexx.TicketBus.TicketBusClient.DataModel.Attribute;


namespace Whatsnexx.Services{

    using Orchard.Security;

    public class TicketBusService : ITicketBusService {
        
        private readonly IOrchardServices _orchardServices;
        private readonly IRepository<WhatsnexxSettingsPartRecord> _settingsRepository;
        private readonly IRepository<WhatsnexxPartRecord> _sendInfogateRepository;

        public TicketBusService(IOrchardServices orchardServices, IRepository<WhatsnexxSettingsPartRecord> settingsRepository, IRepository<WhatsnexxPartRecord> sendInfogateRepository)
        {
            _orchardServices = orchardServices;
            _settingsRepository = settingsRepository;
            _sendInfogateRepository = sendInfogateRepository;
            Logger = NullLogger.Instance;
            T = NullLocalizer.Instance;
        }

        public Localizer T { get; set; }
        public ILogger Logger { get; set; }


        private static string TryGetValueFromDictionary(Dictionary<string, string> datas, string dictionaryKey) 
        {
            var returnValue = "";

            if (datas.ContainsKey(dictionaryKey))
                returnValue = datas[dictionaryKey];

            return returnValue;
        }



        public bool SendEvent(Dictionary<string, string> context)
        {
         
            var infogateSetting = _settingsRepository.Fetch(x => true).OrderByDescending(x => x.Id).FirstOrDefault();
            int formId = Convert.ToInt32(context["FormId"]);
            var sendInfogate = _sendInfogateRepository.Fetch(x => x.Id == formId).FirstOrDefault();
            
            Guid parser;
         
            if (infogateSetting != null && sendInfogate != null && Guid.TryParse(infogateSetting.AccountId, out parser) && Guid.TryParse(sendInfogate.SubjectTypeId, out parser))
            {

                var gatewayStorageAccount = new GatewayStorageAccount(infogateSetting.UserName, infogateSetting.Password, new Guid(infogateSetting.AccountId));
                if (!string.IsNullOrEmpty(infogateSetting.TicketBusUrl))
                {
                    gatewayStorageAccount = new GatewayStorageAccount(infogateSetting.UserName, infogateSetting.Password, new Guid(infogateSetting.AccountId), infogateSetting.TicketBusUrl);
                }

                var ticketBusClient = new TicketBusClient(gatewayStorageAccount);
                var langKey = TryGetValueFromDictionary(context, "LanguageCode");

                if (!String.IsNullOrEmpty(langKey))
                {
                    if (context[langKey] == "True")
                    {
                        context[langKey] = "EN";
                    }
                    if (context[langKey] == "False")
                    {
                        context[langKey] = "FR";
                    }
                }
                var attributeList = new List<Attribute>();
                foreach (var property in context)
                {
                    if (!property.Key.Contains("op") && !property.Key.Contains("__RequestVerificationToken") && !property.Key.Contains("oforms.name")
                        && !property.Key.Contains("ReturnUrl") && !property.Key.Contains("EventName") && !property.Key.Contains("Environment") && !property.Key.Contains("SubjectCode"))
                    {
                        //NOTE: A standard needs to be defined for the attribute naming
                        attributeList.Add(new Attribute() { Name = property.Key, Value = property.Value });
                    }
                }

                //Generic attributes
                attributeList.Add(new Attribute() { Name = "RequestDate", Value = DateTime.Now.ToString("yyyy-MM-dd") });


                try
                {
                    var subjectCode = TryGetValueFromDictionary(context, sendInfogate.SubjectCode);
                    if (!String.IsNullOrEmpty(subjectCode))
                    {
                        ticketBusClient.SendEvent(new Guid(sendInfogate.SubjectTypeId), subjectCode, sendInfogate.EventName, attributeList, (ExecutionEnvironments)Enum.Parse(typeof(ExecutionEnvironments), sendInfogate.Environment));
                        Logger.Debug("Ticket sent for the account {0} to environment {1} in subjectType {2} for the event {3} and the subjectCode {4}", infogateSetting.AccountId, sendInfogate.Environment.ToString(), sendInfogate.SubjectTypeId, sendInfogate.EventName, sendInfogate.SubjectCode);
                    }
                    else
                        Logger.Error("Invalid Subject Code Key={0}]", sendInfogate.SubjectCode);
                    
                }
                catch (Exception ex)
                {
                    Logger.Error(ex, "An unexpected error while sending ticket for the account {0} to environment {1} in subjectType {2} for the event {3} and the subjectCode {4}", infogateSetting.AccountId, sendInfogate.Environment, sendInfogate.SubjectTypeId, sendInfogate.EventName, sendInfogate.SubjectCode);
                }
            }
            else
            {
                Logger.Error("Invalid Settings or form configurations");
            }
            return true;
        }
    }
}
